package com.bestv.search.engine.compass.extend;

import com.bestv.search.common.util.StringConst;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.FieldSelector;
import org.apache.lucene.document.FieldSelectorResult;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.ScoreDocComparator;
import org.apache.lucene.search.SortField;

import java.io.IOException;

public class InfoHeaderItemOrderComparator implements ScoreDocComparator {
    protected final Log log = LogFactory.getLog(getClass());

    private IndexReader reader;
    private FieldSelector fieldSelector;
    private long headerId;

    public InfoHeaderItemOrderComparator(IndexReader reader, long headerId) {
        this.reader = reader;
        this.headerId = headerId;
        this.fieldSelector = new FieldSelector() {
            private static final long serialVersionUID = 5914006583152405828L;

            public FieldSelectorResult accept(String fieldName) {
                if (StringConst.INFOHEADERITEMS.equals(fieldName) || StringConst.ID.equals(fieldName)) {
                    return FieldSelectorResult.LAZY_LOAD;
                } else {
                    return FieldSelectorResult.NO_LOAD;
                }
            }
        };
    }

    public int compare(ScoreDoc doc1, ScoreDoc doc2) {

        int doc1_order = getOrderByHeaderId(doc1, headerId);
        int doc2_order = getOrderByHeaderId(doc2, headerId);

        // Order by maxHitCount desc
        if (doc1_order > doc2_order) {
            return 1;
        } else if (doc1_order == doc2_order) {
            return 0;
        } else {
            return -1;
        }
    }

    public int sortType() {
        return SortField.INT;
    }

    public Comparable<Integer> sortValue(ScoreDoc doc) {
        return getOrderByHeaderId(doc, headerId);
    }

    private int getOrderByHeaderId(ScoreDoc scoreDoc, long headerId) {
        Document doc;
        try {
            doc = reader.document(scoreDoc.doc, fieldSelector);
            String infoHeaderItems = doc.get(StringConst.INFOHEADERITEMS);

            if (infoHeaderItems == null || StringConst.EMPTY.equals(infoHeaderItems)) {
                return 1;
            } else {
                // This field's format is
                // "infoHeader_id info_order infoHeader_id info_order"
                // So, get order as below
                String[] items = infoHeaderItems.split(StringConst.SPACE);
                for (int i = 0; i < items.length; ) {
                    long infoHeader_id = Long.valueOf(items[i]);
                    if (infoHeader_id == headerId) {
                        try {
                            return Integer.valueOf(items[i + 1]);
                        } catch (Exception e) {
                            log.error("Gets order failed for infoHeader:" + infoHeader_id + " and info_id:"
                                    + doc.get(StringConst.ID));
                            return 1;
                        }
                    }
                    i = i + 2;
                }
            }
        } catch (CorruptIndexException e1) {
            log.error("Gets order failed for infoHeader:" + headerId);
            e1.printStackTrace();
        } catch (IOException e1) {
            log.error("Gets order failed for infoHeader:" + headerId);
            e1.printStackTrace();
        }
        return 1;
    }
}